Skip to content

Add background attention notifications#1573

Open
Jabex113 wants to merge 1 commit intopingdotgg:mainfrom
Jabex113:attention-notifications
Open

Add background attention notifications#1573
Jabex113 wants to merge 1 commit intopingdotgg:mainfrom
Jabex113:attention-notifications

Conversation

@Jabex113
Copy link
Copy Markdown

@Jabex113 Jabex113 commented Mar 30, 2026

Closes #376

Summary

This adds a small first slice of local lifecycle notifications in the web app.

Users can now opt into local attention notifications that fire while T3 Code is in the background when:

  • a turn actually settles as completed
  • the agent opens an approval request
  • the agent requests user input

What changed

  • added a new attentionNotifications client setting
  • added an "Attention notifications" toggle in General settings
  • request browser notification permission when the setting is enabled
  • watch thread lifecycle state globally and send notifications only when the app is not in the foreground
  • avoid sending a completion notification when the latest change is actually a new approval or user-input request
  • added focused tests around the lifecycle notification diff logic

Notes

This stays deliberately small and local:

  • no external hook API yet
  • no Electron/main-process integration yet
  • no sound packs or third-party notifier integration yet

The goal here is to cover the basic local notification path first while keeping the completion signal tied to the settled turn state instead of intermediate activity.

Validation

Ran in apps/web:

  • bun x vitest run src/hooks/useLifecycleNotifications.test.ts
  • bun run typecheck
  • bun x oxlint apps/web/src/components/AppSidebarLayout.tsx apps/web/src/components/settings/SettingsPanels.tsx apps/web/src/hooks/useLifecycleNotifications.test.ts apps/web/src/hooks/useLifecycleNotifications.ts apps/web/src/lib/localNotifications.ts apps/web/src/lifecycleNotifications.ts packages/contracts/src/settings.ts

Note

Medium Risk
Adds an opt-in, global side effect that observes thread state and triggers browser Notification API calls, which could cause noisy/duplicated notifications or unexpected behavior across environments if the diffing logic or permission handling is wrong.

Overview
Adds opt-in background “attention notifications” to the web app: a new attentionNotifications client setting and a General Settings toggle that requests local notification permission and warns when blocked/unsupported.

Introduces lifecycle notification plumbing (collectLifecycleNotifications + useLifecycleNotifications) to diff thread snapshots and, when the app is not foregrounded, send local notifications for new approvals, new user-input requests, or a newly settled completed turn (with attention requests taking precedence to avoid misleading completion pings). Includes focused unit tests for the notification diffing behavior.

Written by Cursor Bugbot for commit 775c8ba. This will update automatically on new commits. Configure here.

Note

Add background attention notifications for thread lifecycle events

  • Adds a new attentionNotifications setting (default false) in packages/contracts/src/settings.ts and a toggle in the General Settings panel that requests browser notification permission on enable, surfacing a warning toast if blocked or unsupported.
  • Introduces apps/web/src/lifecycleNotifications.ts with collectLifecycleNotifications, which diffs thread snapshots to emit events for new approval requests, user input requests, and newly settled turn completions, prioritizing attention requests over completions.
  • Adds the useLifecycleNotifications hook, mounted in the app layout, which fires local notifications via the localNotifications module when the setting is enabled and the app is backgrounded (not visible or not focused).
  • Behavioral Change: notifications are only sent while the app is in the background; the first snapshot on mount is used as a baseline so no notifications fire on initial load.

Macroscope summarized 775c8ba.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 245533bb-872e-4eb0-b092-70afbc0d40af

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 30, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 775c8ba40b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const initializedRef = useRef(false);

useEffect(() => {
const nextThreadSnapshot = threads.map((thread) => cloneThreadSnapshot(thread));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip snapshot cloning when notifications are off

This effect clones every thread and activity on each threads update before checking attentionNotifications, so the default-off state still pays an O(total activities) copy cost during normal streaming traffic. In production sessions with long activity histories, this can add avoidable render/effect overhead even though no notifications can be emitted. The guard for disabled notifications should run before building full snapshots (or use a cheaper baseline strategy) to avoid this regression.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: local lifecycle hooks / notification integration for tools like peon-ping

1 participant